/* 	
	Copyright (C) 2011 by Christopher Diggins
	Usage is permitted under the terms of the MIT License 1.0. 	
*/

/** \file 
	Contains implementation of some debugging functions.	
*/

#include "cvm_extra.h"

char* op_name(byte op) {
	switch (op)
	{
	#define OPCODE(NAME, WIDTH, CAT, DESC) case _##NAME: return #NAME;
	#include "opcodes.h"	
	default: return "unknown";	
	}
}

char* op_cat(byte op) {
	switch (op)
	{
	#define OPCODE(NAME, WIDTH, CAT, DESC) case _##NAME: return CAT;
	#include "opcodes.h"	
	default: return "unknown";	
	}
}

char* op_desc(byte op) {
	switch (op)
	{
	#define OPCODE(NAME, WIDTH, CAT, DESC) case _##NAME: return DESC;
	#include "opcodes.h"	
	default: return "unknown";	
	}
}

void print_code(VM* vm) {
	int i=0;
	byte* b = vm_code_begin();
	while (b < vm_code_end()) {
		int width = vm_op_width(*b);
		printf("%s ", op_name(*b));
		b++;
		for (i=1; i < width; ++i)
			printf("%d ", *b++);
	}
	printf("\n");
}

void print_val(Val* v) {
	char s[100];
	val_to_str_buffer(v, s, sizeof(s));
	printf("%s", s);
}

void print_mem(Mem* mem) {
	MemIter iter;
	mem_foreach(&iter, mem) {
		print_val(iter.val);
		printf(" ");
	}
	printf("\n");
}

void print_stk(VM* vm) {
	Val** i;
	for (i=vm->stkbot; i <= vm->sp; ++i) {
		print_val(*i);
		printf(" ");
	}
	printf("\n");
}

void print_stk_aux(VM* vm) {
	Val** i;
	for (i=vm->stktop; i >= vm->ap; --i) {
		print_val(*i);
		printf(" ");
	}
	printf("\n");
}

void print_vm_state(VM* vm) {
	printf("Heap memory: ");
	print_mem(&vm->mem);
	printf("Main stack: ");
	print_stk(vm);
	printf("Auxiliary stack: ");
	print_stk_aux(vm);
	if (vm->ip)
		printf("Evaluating %s\n", op_name(*vm->ip));
	else
		printf("No instruction pointer");
}

void run_debugger(VM* vm) {
	// TODO: 
}

